﻿#include "ThreadCache.h"
#include "CentralCache.h"

void* ThreadCache::Allocate(size_t bytes) // 申请bytes大小内存空间
{
	// 小于256KB向tc申请
	size_t alignBytes = SizeIndex::Align(bytes); // 申请bytes对齐后的大小
	size_t index = SizeIndex::Index(bytes); // 哈希桶的下标
	if (!_freelists[index].Empty())
	{
		return _freelists[index].Pop();
	} 
	else
	{
		return FetehFromCentralCache(alignBytes);
	}
}

void ThreadCache::DeAllocate(void* obj, size_t bytes) // 释放bytes大小内存空间
{
	size_t index = SizeIndex::Index(bytes); // 哈希桶的下标

	_freelists[index].Push(obj);

	if (_freelists[index].Size() >= _freelists[index].InitSize())
	{
		ListTooLong(_freelists[index], bytes);
	}
}

void* ThreadCache::FetehFromCentralCache(size_t alignBytes) // 向中心缓存申请bytes大小内存空间
{
	size_t index = SizeIndex::Index(alignBytes);
	size_t batchsize = min(SizeIndex::maxBatch(alignBytes), _freelists[index].InitSize()); // 最大内存块数量
	if (batchsize == _freelists[index].InitSize()) _freelists[index].InitSize()++;  // 递增每次获取的内存块数量

	void* start = nullptr, *end = nullptr; // 内存块的首尾地址
	size_t actulSize = CentralCache::GetInstance()->FetchRangeObj(start, end, batchsize, alignBytes); // 向中心缓存获取内存块

	if (actulSize > 1) // 将第一个内存块返回给程序使用，多余的插入到freelist中
	{
		void* next = *(void**)start;
		// 头插
		_freelists[index].Push(next, end, actulSize - 1);
	}

	return start;
}

void ThreadCache::ListTooLong(FREELIST& freelist, size_t bytes)
{
	void* start = nullptr, * end = nullptr; // 输出型参数
	freelist.PopRange(start, end, freelist.InitSize());

	CentralCache::GetInstance()->ReleaseToSpan(start, bytes);
}

